package org.codingq92.basic;

import java.util.concurrent.ConcurrentHashMap;

/**
 * ConcurrentHashMap测试<br/><br/>
 * &: 都为1才是1，否则得 0。<br/>
 * ^: 不同则得 1，相同则得 0。<br/>
 * <p>
 * 1.为什么计算元素的下标需要 用数组的长度-1然后再去 & hash值？<br/>
 * 解析：因为16的二进制是：00000000 00000000 00000000 00010000<br/>
 * 随便找一个数字的二进制数00000000 00000000 00000000 00000001<br/>
 * 因为 & 运算 都为1才是1 否则都是0 所以 上面的运算就变成了 00000000 00000000 00000000 00000000 比较大的概率造成hash冲突<br/>
 * 所以需要 长度-1 变 15，15的二进制是 00000000 00000000 00000000 00001111 这样在 & 运算 就大大的减少了hash冲突<br/><br/>
 * <p>
 * 2.为什么计算元素的hash值需要 (h ^ (h >>> 16)) & HASH_BITS（0x7fffffff：01111111 11111111 11111111 11111111） ？<br/>
 * 因为不这样 高位就无法参与hash计算，将高位右移16位和自己的低位16位进行异或得到新的值再去计算hash<br/>
 * 就可以保证高位低位都参与到了运算 减少hash冲突<br/>
 * & HASH_BITS : 目的，保证一定是一个正数,因为负数有特殊含义<br/>
 * static final int MOVED     = -1; // 正在迁移。实现并发扩容，允许多线程协助迁移数据，提高扩容效率。
 * static final int TREEBIN   = -2; // 红黑树结构 树节点
 * static final int RESERVED  = -3; // 表示当前节点是一个 保留节点（ReservationNode），用于占位。保证原子性操作，避免竞态条件。
 *
 * @author: CodingQ92
 * @date: 2025/6/10 21:44
 */
public class ConcurrentHashMapTest {

    private static final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        map.put("key", 1);
        System.out.println(String.format("%32s", Integer.toBinaryString(1)).replace(' ', '0'));
        System.out.println(String.format("%32s", Integer.toBinaryString(2)).replace(' ', '0'));
        System.out.println("----------------------------------------");
        System.out.println(String.format("%32s", Integer.toBinaryString(1 & 2)).replace(' ', '0'));
        System.out.println(String.format("%32s", Integer.toBinaryString(1 ^ 2)).replace(' ', '0'));
    }
//    ConcurrentHashMap.putVal()函数详细解析
//    final V putVal(K key, V value, boolean onlyIfAbsent) {
//        // 1.key val 不可为null
//        if (key == null || value == null) throw new NullPointerException();
//        // 2.计算key的hash值
//        // spread具体实现 (h ^ (h >>> 16)) & HASH_BITS
//        // & 运算：都为1才是1 否则都是0
//        int hash = spread(key.hashCode());
//        int binCount = 0;
//        for (ConcurrentHashMap.Node<K,V>[] tab = table;;) {
//            // f: 当前下标的数组元素Node
//            // n: 数组长度
//            // i: 当前元素在数组中的下标
//            ConcurrentHashMap.Node<K,V> f; int n, i, fh; K fk; V fv;
//            // 数组不存在 || 数组长度为空 直接初始化
//            if (tab == null || (n = tab.length) == 0)
//                tab = initTable();
//            // 数组存在 利用自旋锁 存入数据
//            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
//                if (casTabAt(tab, i, null, new ConcurrentHashMap.Node<K,V>(hash, key, value)))
//                    break;                   // no lock when adding to empty bin
//            }
// 省略代码.......
}
